k近邻法-k_Nearest Neighbors

k近邻法(knn)就一种基本分类与回归方法。 image

from scipy.spatial import minkowski_distance
def classify0(inX, dataSet, labels, k):
  #    dataSetSize = dataSet.shape[0]
  #    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
  #    sqDiffMat = diffMat **2
  #    sqDistances = sqDiffMat.sum(axis=1)
  #    distances = sqDistances**0.5
  #    print('distances', distances)
    distances = minkowski_distance(inX, dataSet) #计算inX与与dataSet各个点的距离,返回个array
    sortedDistIndicies = distances.argsort()     #返回排序后的元素下标
    classCount = {}

    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]] #获得对应的label
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
        # 对classCount根据键值进行排序
        sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

# 将txt转换为矩阵
def file2matrix2(filename):
    data = np.genfromtxt(filename, dtype='|U8')
    returnMat = data[:, 0:-1].astype('float64')
    return returnMat, data[:,-1]

# 数据进行规格化处理
def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = np.zeros(dataSet.shape)
    m = dataSet.shape[0]
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    normDataSet = normDataSet/np.tile(ranges, (m,1))
    return normDataSet, ranges, minVals

 # 这里使用了scikit-learn中的API,结果与autoNorm是一样的
def autoNorm2(dataSet):
    from sklearn.preprocessing import normalize
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    normDataSet = normalize(dataSet, norm='max',axis=0)
    return normDataSet, maxVals-minVals, minVals

# 将txt文件转换为向量
 def img2vec(filename):
     rVec = np.zeros((1,1024))
     f = open(filename)
     for i in range(32):
         line = f.readline()
         for j in range(32):
             rVec[0, 32*i+j] = int(line[j])
    return rVec

# 对手写数字进行测试
def handwritingClassTest():
     hwLabels = []
     trainFileList = os.listdir('digits/trainingDigits/')
     m = len(trainFileList)
     trainingMat = np.zeros((m, 1024))
     for i in range(m):
         filename = trainFileList[i]
         className = int(filename.split('_')[0])
         hwLabels.append(className)
         trainingMat[i,:] = img2vec('digits/trainingDigits/%s' % filename)
     testFileList = os.listdir('digits/testDigits')
     accuracyCount = 0.0
     mTest = len(testFileList)
     for i in range(mTest):
         filename = testFileList[i]
         className = int(filename.split('_')[0])
         vecTest = img2vec('digits/testDigits/%s' % filename)
         classifierResult = classify0(vecTest, trainingMat, hwLabels, 1)
         if classifierResult == className:
             accuracyCount += 1
     print("the total accuracy rate is: %f" % (accuracyCount/mTest))

完整代码


在正式进行数据挖掘之前,尤其是使用基于对象距离的 挖掘算法时,如:神经网络、最近邻分类等,必须 进行数据规格化。也就是将其缩至特定的范围之内,如:[0,10]。如:对于一 个顾客信息数据库中的年龄属性或工资属性,由于工资属性的取值比年龄属性的 取值要大许多,如果不进行规格化处理,基于工资属性的距离计算值显然将远超 过基于年龄属性的距离计算值,这就意味着工资属性的作用在整个数据对象的距 离计算中被错误地放大了。 规格化就是将一个属性取值范围投射到一个特定范围之内,以消除数值型属 性因大小不一而造成挖掘结果的偏差。规划化处理常常用于神经网络、基于距离 计算的最近邻分类和聚类挖掘的数据预处理。 。对于神经网络,采用规格化后的数据不仅有助于确保学习结果的正确性,而且也会帮助提高学习的速度。对于基于距离计算的挖掘,规格化方法可以帮助消除因属性取值范围不同而影响挖掘结果 的公正性。
三种规格化方法:

1.最大最小规格化方法 该方法对初始数据进行一种线性转换。设$ min{A} $和$ max{A} $为属性A的最小和最大值。最大最小规格化方法将属性A的一个值映射为$ v^{‘} $且有$ v^{‘} \in [newmin{A},newmax{A}] $,具体映射公式如下: $ v^{‘} = \frac{v-min{A}}{max{A}-min{A}} (new_max{A}-new_min_{A})+new_min_{A} $

2.零均值规格化方法。该方法是根据属性A的均值和偏差来对A进行规格化。属性A的v值可以通过以下计算公式获得其映射值$ v^{‘} $ $ v^{‘} = \frac{v-\bar A}{\sigma{A}} $
其中的$ \bar A $和$ \sigma
{A} $分别为属性A的均值和方差。这种规格化方法常用于属性A最大值与最小值未知,或使用最大最小规格化方法时会出现异常数据的情况。

3.十基数变换规格化方法。 该方法通过移动属性A值的小数位置来达到规格化的目的。把移动的小数位取决于属性a绝对值的最大值。属性A的v值可以通过以下计算公式获得其映射值$ v^{‘} $。 $ v^{‘} = \frac{v}{10^{j}} $ 其中j为使$ \max(|v^{‘}|) \lt 1 $成立的最小值。


Ref:
1.统计学习方法-李航
2.数据挖掘导论
3.机器学习实战